﻿using Microsoft.Win32;
using NIDViewer.Extension;
using NIDViewer.Helper;
using NIDViewer.Model;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Navigation;

namespace NIDViewer
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private ObservableCollection<ComboBoxItemModel> _channelTypes;
        private int _selectedChannelId;
        private string NidFilePath;

        public ObservableCollection<ComboBoxItemModel> ChannelTypes
        {
            get => _channelTypes;
            set
            {
                _channelTypes = value;
                OnPropertyChanged();
            }
        }

        public int SelectedChannelId
        {
            get => _selectedChannelId;
            set
            {
                _selectedChannelId = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this; // 设置 DataContext 为当前窗口实例
            InitChannelType();
        }

        private void InitChannelType()
        {
            ChannelTypes = new ObservableCollection<ComboBoxItemModel>();
            foreach (DataChannelTypes channel in Enum.GetValues<DataChannelTypes>())
            {
                ChannelTypes.Add(new ComboBoxItemModel
                {
                    Name = channel.ToString(),
                    Id = (int)channel,
                });
            }
            if (ChannelTypes.Count > 0)
            {
                SelectedChannelId = ChannelTypes[0].Id;
            }
        }

        private async void BtnNidOpenClick(object sender, RoutedEventArgs e)
        {
            try
            {
                SelectedChannelId = (int)DataChannelTypes.Z_Axis_Forward;
                ComboBoxChannel.IsEnabled = true;
                var ofd = new OpenFileDialog { Filter = "NID files|*.nid;*.NID" };
                if (ofd.ShowDialog() != true) return;

                NidFilePath = ofd.FileName;

                #region NIDFileReader 读取

                //var reader = new NIDFileReader(ofd.FileName);
                //var (configParser, nidDataInfo, imageData, specData, spectrumData) = reader.GetData();
                //var Points = Convert.ToInt32(reader["Points"][1]);
                //var Lines = Convert.ToInt32(reader["Lines"][1]);
                //var MeasureWidth = Convert.ToDouble(reader["Dim0Range"][1]);
                //var MeasureHeight = Convert.ToDouble(reader["Dim1Range"][1]);
                //var data = reader.GetMatrixData(DataChannelTypes.Z_Axis_Forward);
                //var matrices = data.ToArray<double>().ToList();

                #endregion

                #region NidParser 读取

                byte[] bytes = await File.ReadAllBytesAsync(ofd.FileName);
                var parser = new NidParser(bytes);
                var nidData = parser.GetMatrixData(DataChannelTypes.Z_Axis_Forward);
                var Points = nidData.Points;
                var Lines = nidData.Lines;
                var MeasureWidth = nidData.MeasureWidth;
                var MeasureHeight = nidData.MeasureHeight;
                var data = nidData.Matrix;
                var matrices = data.Data.ToList();

                #endregion

                var flattenResponse = new DpService().FlattenImage(new FlattenImageRequest
                {
                    Mask = new List<double>(),
                    Matrix = matrices,
                    FlattenType = Enums.FlattenAlgorithm.PER_LINE_1,
                    Lines = Lines,
                    Points = Points
                });
                if (flattenResponse.IsError)
                {
                    TxtInfo.Text = $"拉平失败";
                }
                matrices = flattenResponse.Matrix;

                TxtInfo.Text = "解析中...";
                ListMatrices.Items.Clear();
                ListMatrices.Items.Add($"Matrix:矩阵: {matrices.Count}");
                ListMatrices.Items.Add($"Point:{Points} ,Lines{Lines}");
                ListMatrices.Items.Add($"物理尺寸: {MeasureWidth} μm x {MeasureHeight}μm");

                (Width, Height) = CalculateScaledSize(MeasureWidth, MeasureHeight, 400, 400, 100, 100);

                var enhancedImage = ImageTool.GeneratePicture(matrices, Points, Lines, (int)Width, (int)Height);
                var grayscaleImage = ImageTool.GenerateGrayPicture(matrices, Points, Lines);

                ImgOriginalMatrix.Source = enhancedImage;
                ImgThumbnail1.Source = grayscaleImage;
                ImgThumbnail2.Source = enhancedImage;
            }
            catch (Exception ex)
            {
                TxtInfo.Text = $"错误: {ex.Message}\n{ex.StackTrace}";
            }
        }

        private void BtnTiffOpenClick(object sender, RoutedEventArgs e)
        {
            try
            {
                SelectedChannelId = (int)DataChannelTypes.Z_Axis_Forward;
                ComboBoxChannel.IsEnabled = false;
                var ofd = new OpenFileDialog { Filter = "Tiff files|*.tiff;*.tiff" };
                if (ofd.ShowDialog() != true) return;

                TIFFINFO info = new TIFFINFO();
                var success = TiffHelper.ReadDataFromTiff(ofd.FileName, info);
                if (!success)
                {
                    TxtInfo.Text = $"Tiff读取失败";
                    return;
                }
                var Points = info.XOriginRes;
                var Lines = info.YOriginRes;
                var MeasureWidth = info.XReal;
                var MeasureHeight = info.YReal;
                var matrices = info.OriginPoints.Select(x => x * 1e-6).ToList();

                var flattenResponse = new DpService().FlattenImage(new FlattenImageRequest
                {
                    Mask = new List<double>(),
                    Matrix = matrices,
                    FlattenType = Enums.FlattenAlgorithm.PER_LINE_1,
                    Lines = Lines,
                    Points = Points
                });
                if (flattenResponse.IsError)
                {
                    TxtInfo.Text = $"拉平失败";
                }
                matrices = flattenResponse.Matrix;

                TxtInfo.Text = "解析中...";
                ListMatrices.Items.Clear();
                ListMatrices.Items.Add($"Matrix:矩阵: {matrices.Count}");
                ListMatrices.Items.Add($"Point:{Points} ,Lines{Lines}");
                ListMatrices.Items.Add($"物理尺寸: {MeasureWidth}m x {MeasureHeight}m");

                (Width, Height) = CalculateScaledSize(MeasureWidth, MeasureHeight, 800, 600, 100, 100);

                var enhancedImage = ImageTool.GeneratePicture(matrices, Points, Lines, (int)Width, (int)Height);
                var grayscaleImage = ImageTool.GenerateGrayPicture(matrices, Points, Lines);

                ImgOriginalMatrix.Source = enhancedImage;
                ImgThumbnail1.Source = grayscaleImage;
                ImgThumbnail2.Source = enhancedImage;
            }
            catch (Exception ex)
            {
                TxtInfo.Text = $"错误: {ex.Message}\n{ex.StackTrace}";
            }
        }

        public static (int newWidth, int newHeight) CalculateScaledSize(
    double originalWidth, double originalHeight,
    int maxWidth, int maxHeight,
    int minWidth = 0, int minHeight = 0)
        {
            if (originalWidth <= 0 || originalHeight <= 0)
                throw new ArgumentException("原始宽高必须大于0");

            // 计算宽高比
            double aspectRatio = (double)originalWidth / originalHeight;

            // 基于最大尺寸计算缩放比例
            double widthRatio = (double)maxWidth / originalWidth;
            double heightRatio = (double)maxHeight / originalHeight;

            // 取较小的比例以确保不超出最大边界
            double scale = Math.Min(widthRatio, heightRatio);

            // 计算新尺寸
            int newWidth = (int)(originalWidth * scale);
            int newHeight = (int)(originalHeight * scale);

            // 应用最小值限制
            if (minWidth > 0) newWidth = Math.Max(newWidth, minWidth);
            if (minHeight > 0) newHeight = Math.Max(newHeight, minHeight);

            // 确保不超出最大值（在应用最小值后可能需要重新调整）
            if (newWidth > maxWidth || newHeight > maxHeight)
            {
                // 如果超出最大值，重新基于最大值计算
                widthRatio = (double)maxWidth / newWidth;
                heightRatio = (double)maxHeight / newHeight;
                scale = Math.Min(widthRatio, heightRatio);

                newWidth = (int)(newWidth * scale);
                newHeight = (int)(newHeight * scale);
            }

            return (newWidth, newHeight);
        }

        private async void BtnNidToTiffClick(object sender, RoutedEventArgs e)
        {
            try
            {
                var ofd = new OpenFileDialog { Filter = "NID files|*.nid;*.NID" };
                if (ofd.ShowDialog() != true) return;

                #region NidParser 读取

                byte[] bytes = await File.ReadAllBytesAsync(ofd.FileName);
                var parser = new NidParser(bytes);
                var nidData = parser.GetMatrixData(DataChannelTypes.Z_Axis_Forward);
                var Points = nidData.Points;
                var Lines = nidData.Lines;
                var MeasureWidth = nidData.MeasureWidth;
                var MeasureHeight = nidData.MeasureHeight;
                var data = nidData.Matrix;
                var matrices = data.Data.ToList();

                #endregion

                var flattenResponse = new DpService().FlattenImage(new FlattenImageRequest
                {
                    Mask = new List<double>(),
                    Matrix = matrices,
                    FlattenType = Enums.FlattenAlgorithm.PER_LINE_1,
                    Lines = Lines,
                    Points = Points
                });
                if (flattenResponse.IsError)
                {
                    TxtInfo.Text = $"拉平失败";
                    return;
                }
                matrices = flattenResponse.Matrix;
                var enhancedImage = ImageTool.GeneratePicture(matrices, Points, Lines);

                //(byte[] flattenedImage, int width, int height) = ImageTool.GenerateShowPoints(matrices, Points, Lines, MeasureWidth, MeasureHeight);
                (byte[] flattenedImage, int width, int height) = ImageGenerator.GenerateShowPoints(matrices, Points, Lines, MeasureWidth, MeasureHeight);
                File.WriteAllBytes(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "output.png"), ImageTool.BitmapSourceToByteArray(enhancedImage));
                TIFFINFO info = new TIFFINFO
                {
                    XOriginRes = Points,
                    YOriginRes = Lines,
                    XReal = MeasureWidth,
                    YReal = MeasureHeight,
                    Angle = 0,
                    XyUnit = "um",
                    ZUnit = "um",
                    OriginPoints = matrices,
                    //ShowPoints = BitmapSourceToRGBBytes(enhancedImage).ToList(),
                    //XShowRes = enhancedImage.PixelWidth,
                    //YShowRes = enhancedImage.PixelHeight,
                    ShowPoints = flattenedImage.ToList(),
                    XShowRes = width,
                    YShowRes = height,
                };
                TiffHelper.WriteDataToTiff(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "output.tiff"), info);
            }
            catch (Exception ex)
            {
                TxtInfo.Text = $"错误: {ex.Message}\n{ex.StackTrace}";
            }
        }

        public byte[] BitmapSourceToRGBBytes(BitmapSource bitmapSource)
        {
            int width = bitmapSource.PixelWidth;
            int height = bitmapSource.PixelHeight;
            int stride = width * (bitmapSource.Format.BitsPerPixel / 8); // 计算每行的字节数
            byte[] pixels = new byte[width * height * (bitmapSource.Format.BitsPerPixel / 8)]; // 初始化字节数组以存储所有像素数据
            bitmapSource.CopyPixels(pixels, stride, 0); // 将像素数据复制到数组中
            return pixels; // 返回像素数据数组（已经是RGB格式）
        }

        private void BtnSaveImage_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (ImgOriginalMatrix.Source == null)
                {
                    MessageBox.Show("没有可保存的图像", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }

                var saveDialog = new SaveFileDialog
                {
                    Filter = "PNG图像|*.png|JPEG图像|*.jpg|BMP图像|*.bmp|所有文件|*.*",
                    DefaultExt = "png",
                    FileName = $"NID_Matrix_{DateTime.Now:yyyyMMdd_HHmmss}"
                };

                if (saveDialog.ShowDialog() == true)
                {
                    var bitmapSource = (BitmapSource)ImgOriginalMatrix.Source;
                    var encoder = GetEncoder(saveDialog.FileName);

                    if (encoder != null)
                    {
                        encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
                        using (var stream = File.Create(saveDialog.FileName))
                        {
                            encoder.Save(stream);
                        }
                        MessageBox.Show($"图像已保存到: {saveDialog.FileName}", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存图像时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private BitmapEncoder GetEncoder(string fileName)
        {
            var extension = System.IO.Path.GetExtension(fileName).ToLower();
            return extension switch
            {
                ".png" => new PngBitmapEncoder(),
                ".jpg" or ".jpeg" => new JpegBitmapEncoder(),
                ".bmp" => new BmpBitmapEncoder(),
                _ => new PngBitmapEncoder()
            };
        }

        private void ComboBoxChannel_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                if (ComboBoxChannel.SelectedItem is ComboBoxItemModel selectedChannel)
                {
                    TxtCurrentChannel.Text = selectedChannel.Name;
                    ListMatrices.Items.Clear();
                    ImgOriginalMatrix.Source = null;
                    ImgPhysicalMatrix.Source = null;
                    ImgThumbnail1.Source = null;
                    ImgThumbnail2.Source = null;
                    try
                    {
                        var channelType = (DataChannelTypes)selectedChannel.Id;

                        if (string.IsNullOrWhiteSpace(NidFilePath))
                        {
                            return;
                        }
                        byte[] bytes = File.ReadAllBytes(NidFilePath);
                        var parser = new NidParser(bytes);
                        var nidData = parser.GetMatrixData(channelType);
                        var Points = nidData.Points;
                        var Lines = nidData.Lines;
                        var MeasureWidth = nidData.MeasureWidth;
                        var MeasureHeight = nidData.MeasureHeight;
                        var data = nidData.Matrix;
                        if (data != null)
                        {
                            var matrices = data.Data.ToList();
                            var enhancedImage = ImageTool.GeneratePicture(matrices, Points, Lines);
                            var grayscaleImage = ImageTool.GenerateGrayPicture(matrices, Points, Lines);

                            ImgOriginalMatrix.Source = enhancedImage;
                            ImgPhysicalMatrix.Source = grayscaleImage;
                            ImgThumbnail1.Source = grayscaleImage;
                            ImgThumbnail2.Source = enhancedImage;

                            TxtInfo.Text += $"\n切换到Channel: {selectedChannel.Name}\n";
                            TxtInfo.Text += $"数据点数: {matrices.Count}\n";
                            TxtInfo.Text += $"测量尺寸: {MeasureWidth}μm x {MeasureHeight}μm\n";
                        }
                    }
                    catch (Exception ex)
                    {
                        TxtInfo.Text += $"\n加载Channel数据时出错: {ex.Message}\n";
                    }
                }
            }
            catch (Exception ex)
            {
                TxtInfo.Text += $"\nChannel切换错误: {ex.Message}";
            }
        }
    }
}
